#include <assert.h>
#include <iostream>
#include <fstream> // pour les fichiers
#include <sstream> //pour la conversion du numero de la zone en string

#include "Recuperer.h"
#include "../Personnages/MonstreDePres.h"
#include "../Objets/Objet.h"


using namespace std;


Recuperer::Recuperer() : m_numZoneActive(0), m_hauteur(0), m_largeur(0) {}
Recuperer::~Recuperer(){}


void Recuperer::RecupererZone(Zone* zon, int numZoneActive){

    //Sauvegarde du chemin relatif dans un string
    ostringstream conversion;
    conversion << numZoneActive;
    string numZone = conversion.str();

    string cheminCarte = "Cartes/Zone" + numZone + "/Zone.txt";

    //Ouverture du fichier en lectur
    ifstream carte_zone(cheminCarte.c_str(), ios::in);
    assert(carte_zone); //on vérifie si la carte à bien été ouverte


    string caracteres;  //variable qui stockera les caracteres du fichier

    //On recupere et on sauvegarde la taille de la zone
    getline(carte_zone, caracteres); // premiere ligne = largeur de la zone
    istringstream convert(caracteres);
    convert >> m_largeur;
    zon->SetLargeur(m_largeur); //doublon pour la Largeur

    convert.clear(); //obligatoire si on veut récupérer la seconde valeur

    getline(carte_zone, caracteres);  // deuxieme ligne = hauteur de la zone
    convert.str(caracteres);
    convert >> m_hauteur;
    zon->SetHauteur(m_hauteur); //doublon pour la Hauteur

    //Initialisation de la taille du Calque
    m_largeur=zon->GetLargeur();
    m_hauteur=zon->GetHauteur();

    //Initialisation de la zone
    zon->CreerZone();

    //Remplissage de la zone
    for (int y=0; y<m_hauteur;y++)
    {
        getline(carte_zone, caracteres); //   On recupere la ligne suivante
        int largeur_a_remplir=caracteres.size(); //la ligne ne comportera pas forcement m_largeur caractères
        for (int x=0; x<largeur_a_remplir;x++)
        {
            char ascii = caracteres[x];
            zon->SetCharXY(x,y,ascii);
        }
    }

    carte_zone.close();

}


//Decouper le x, y et le type
int Recuperer::GetXYType(const std::string chaine, int& x, int& y, std::string& type){

    istringstream convert;

    //variable de string et variable pour les tailles de ces strings
    string x_string,y_string;
    int taille_x, taille_y, taille_type;

    int taille_cumule=0; // on cumule la taille de chaque string recupere

    //ex : si on a 20;15-0:100/0 -> 0='2', 1='0', 2=';' 3='1' 4='5' 5='-' 6='0'
    // Pour l'ex : nbr de char pour x = 2
    taille_x = chaine.find_first_of(';');

    //Pour l'ex : on part du char 0, on recupere 2 char -> le numero 0 et 1
    x_string= chaine.substr(0,taille_x);//Pour l'ex : -> |20|;15-0

    // taille_cumule = ( |X| + |;| )
    taille_cumule=taille_x+1;

    // Pour l'ex : taille de y = 5 - 2 - 1 (le char ';') = 2
    taille_y = chaine.find_first_of('-')-taille_cumule;

    // Pour l'ex : on part du 2 + ';' = 3 ieme char, on recupere 2 char -> le numero 3 et 4
    y_string= chaine.substr(taille_cumule,taille_y); //Pour l'ex : -> 20;|15|-0

    // taille_cumule = |X| + |;| + ( |Y| + |-| )
    taille_cumule+=taille_y+1;

    // si : n'est pas dans la liste, (2^32 -1) est retourne
    if(chaine.find_first_of(':') < 100)
    {
        // Pour l'ex : taille du type'= 7 - 2(le x) - 1 (le char ';') - 2(le y) - 1 (le char '-')   = 1
        taille_type=chaine.find_first_of(':')-taille_cumule;

        // Pour l'ex : X;Y-T, on recupere T le type -> 20;15-|0|
        type = chaine.substr(taille_cumule,taille_type);

        // taille_cumule =    |X|   +|;|+   |Y|    +|-|+     |T|       +|:|
        // taille_cumule = taille_x + 1 + taille_y + 1 +  taille_type + 1
        taille_cumule+=taille_type+1;
    }

    else //il n'y a pas d autre variable a recuperer
    {type = "0";}//le type 0 est l herbe

    convert.str(x_string);
    convert >> x; // on reutilise le x qui servait de compteur
    convert.clear();

    convert.str(y_string);
    convert >> y; // de meme pour le y
    convert.clear();

    return taille_cumule;
}



void Recuperer::RecupererTabDeCells(TabDeCells* TabDeCell, int numZoneActive){

    int taille_cumule=0;


//>---------------Monstres qui attaqueront de Près (MDP)------------<


    //Sauvegarde du chemin relatif jusqu'au fichier dans un string
    ostringstream conversion;
    conversion << numZoneActive;
    string numZone = conversion.str();

    string cheminMonstres = "Cartes/Zone" + numZone + "/Monstres.txt";

    //Ouverture du fichier et vérification
    ifstream carte_monstres(cheminMonstres.c_str(), ios::in);
    assert(carte_monstres);

    //Initialisation des variables pour le chargement
    string monstre;
    getline(carte_monstres, monstre); //ligne d'exemple pour un monstre, on en a pas besoin
    getline(carte_monstres, monstre); //ligne pour recuperer le type de monstre, on ne sen servira pas

    string type;
    int x, y;

    int vie, taille_vie, mana;
    string vie_string;
    string mana_string;

    istringstream convert;

    //Chargement de la zone dans le tableau
    while (getline(carte_monstres, monstre))
    {

        if(monstre == "<-Suivant->")
        {
            getline(carte_monstres, monstre); //on recupere la categorie contenue
            getline(carte_monstres, monstre); //on passe a la ligne suivante
        }

        //Decoupage du string X;Y-Type:Vie/Mana
        taille_cumule=GetXYType(monstre,x,y,type);

        if(monstre.find_first_of(':') < 100) //Alors la 'vie' est definie
        {
            if(monstre.find_first_of('/') < 100) //Alors la 'mana' est definie
            {
                taille_vie=monstre.find_first_of('/')-taille_cumule;

                // Pour l'ex : vie =100
                vie_string= monstre.substr(taille_cumule,taille_vie);

                // taille_cumule = |X| + |;| + |Y| + |-| + |T| + |:| + |Vie| + |/|
                taille_cumule+=taille_vie+1;

                // Pour l'ex : mana = 0, on recupere jusqu'à la fin du string
                mana_string= monstre.substr(taille_cumule);
            }
            else //la mana n'est pas definie
            {vie_string= monstre.substr(taille_cumule);}
        }


        //Conversions des string en chaine de caractere
        //x,y et le type sont obligatoirement initialises, la vie et la mana sont facultatifs

        if(vie_string.length() != 0)
        {
            convert.str(vie_string);
            convert >> vie;
            convert.clear();
        }
        else vie=100;

        if(mana_string.length() != 0)
        {
            convert.str(mana_string);
            convert >> mana;
            convert.clear();
        }
        else mana=0;

        //Instanciations des Monstres qui attaqueront De Pres
        MonstreDePres* UnMonstre= new MonstreDePres(x, y, type,vie,mana);
        TabDeCell->SetAdresseDsCell(x,y,UnMonstre);
        TabDeCell->SetDsListe(TabDeCell->GetListeDeMonstres(), (CP*)UnMonstre);

    } //Fin du while

    carte_monstres.close();


//>---------------Fin pour les Monstres qui attaqueront de Pres------------<


//>---------------Monstres qui attaqueront de Loin (MDL)------------<

//A coder

//>---------------Fin pour les Monstres qui attaqueront de Loin------------<


//>---------------Objets------------<

//Code similaire aux precedant

    string cheminObjets = "Cartes/Zone" + numZone + "/Objets.txt";

    //Ouverture du fichier et vérification
    ifstream carte_objets(cheminObjets.c_str(), ios::in);
    assert(carte_objets);

    //Initialisation des variables pour le chargement
    string objet;
    getline(carte_objets, objet); //ligne d'exemple pour un objet, on en a pas besoin
    getline(carte_objets, objet); //ligne pour recuperer le type de l'objet, on ne sen servira pas

    //nouveaux elements
    string poussable_string, poids_string, accroche_string;
    bool poussable, accroche; //accroche : pour le grappin
    int poids;

    //x,y,vie et mana on deja ete definit. On va les reutiliser
    vie_string="";
    mana_string="";
    type="0";

    //Chargement de la zone dans le tableau
    while (getline(carte_objets, objet))
    {

        if(objet == "<-Suivant->")
        {
            getline(carte_objets, objet); //on recupere la ligne qui definie le type
            getline(carte_objets, objet); //on passe a la ligne suivante
        }

        //Decoupage du string, X;Y-Type:Poussable~Poids~Accroche:Vie/Mana
        taille_cumule=GetXYType(objet,x,y,type); ///X,Y et Type

        //ce qui sera entre des tildes '~' sera de taille egal a 1

        if(objet.find_first_of(':') < 100) //Alors la 'Poussable' est definie
        {
            if(objet.find_first_of('~') < 100) //Alors la 'Poids' est definie
            {
                //on va travailler sur le reste de la chaine, a cause des tildes
                objet = objet.substr(taille_cumule); //=Poussable~Poids~Accroche~Vie/Mana
                taille_cumule=0; //on reinitialise

                //on recupere le premier nombre avant le premier '~'
                poussable_string = objet.substr(0,1);

                if(objet.find_first_of('~') < 100) //Poids
                {
                    objet = objet.substr(2); //=Poids~Accroche~Vie/Mana

                    poids_string = objet.substr(0,1);

                    if(objet.find_first_of(':') < 100) //Accroche
                    {
                        objet = objet.substr(2); //=Accroche~Vie/Mana

                        accroche_string = objet.substr(0,1);

                        if(objet.find_first_of('/') >= 0) //Vie et Mana
                        {
                            objet = objet.substr(2); //=Vie/Mana

                            taille_cumule=objet.find_first_of('/'); //nbr de char avant '/'

                            vie_string = objet.substr(0,taille_cumule);

                            //taille_cumule+1 = |Vie| + |/|
                            mana_string = objet.substr(taille_cumule+1); //= Mana -> reste de la chaine

                        } //Sinon Vie
                        else{vie_string= objet.substr();}

                    } //Sinon Accroche
                    else{accroche_string= objet.substr();}

                } //Sinon Poids
                else{poids_string= objet.substr();}

            } //Sinon Poussable
            else
            {poussable_string= objet.substr(taille_cumule);}
        }

        //Conversions des string

        if(poussable_string.length() != 0)
        {
            convert.str(poussable_string);
            convert >> poussable;
            convert.clear();
        }
        else poussable=0;

        if(poids_string.length() != 0)
        {
            convert.str(poids_string);
            convert >> poids;
            convert.clear();
        }
        else poids=0;

        if(accroche_string.length() != 0)
        {
            convert.str(accroche_string);
            convert >> accroche;
            convert.clear();
        }
        else accroche=0;

        if(vie_string.length() != 0)
        {
            convert.str(vie_string);
            convert >> vie;
            convert.clear();
        }
        else vie=10;

        if(mana_string.length() != 0)
        {
            convert.str(mana_string);
            convert >> mana;
            convert.clear();
        }
        else mana=0;

        //Instanciation de l'Objet
        Objet* UnObjet= new Objet(x, y, type,poussable,poids,accroche,vie,mana);
        TabDeCell->SetAdresseDsCell(x,y,UnObjet);

    } //Fin du while

    carte_objets.close();

//>---------------Fin pour les Objets------------<
}
